package com.xhga.client;

import com.xhga.common.RpcDecoder;
import com.xhga.common.RpcEncoder;
import com.xhga.common.RpcRequest;
import com.xhga.common.RpcResponse;
import com.xhga.register.RpcDiscover;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * Created by Hua wb on 2018/11/29.
 */
public class RpcClient extends SimpleChannelInboundHandler<RpcResponse> {

    private RpcResponse rpcResponse;
    private RpcRequest rpcRequest;
    private Object object = new Object();
    private RpcDiscover rpcDiscover;

    public RpcClient(RpcRequest rpcRequest) {
        this.rpcRequest = rpcRequest;
        this.rpcDiscover = new RpcDiscover();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcResponse msg) throws Exception {
        this.rpcResponse = msg;
        synchronized (object){
            ctx.flush();
            object.notifyAll();
        }
    }

    public RpcResponse send()  throws Exception {
        //创建一个socket通信对象
        Bootstrap client = new Bootstrap();
        //创建一个通信组,负责Channel(通道)的I/O事件的处理
        NioEventLoopGroup loopGroup = new NioEventLoopGroup();
        try{
            client.group(loopGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline()
                                    .addLast(new RpcEncoder(RpcRequest.class))
                                    .addLast(new RpcDecoder(RpcResponse.class))
                                    .addLast(RpcClient.this);
                        }
                    }).option(ChannelOption.SO_KEEPALIVE, true);;
            String serverAddress = rpcDiscover.discoverServer();
            System.out.println("服务器地址：" + serverAddress);
            String host = serverAddress.split(":")[0];
            int port = Integer.valueOf(serverAddress.split(":")[1]);
            ChannelFuture future = client.connect(host,port).sync();
            future.channel().writeAndFlush(rpcRequest).sync();
            synchronized (object){
                object.wait();
            }
            if (rpcResponse != null) {
                future.channel().closeFuture().sync();
            }
            return rpcResponse;
        }finally {
            loopGroup.shutdownGracefully();
        }
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        ctx.close();
    }

}
